package com.sunwayworld.basemodule.business.batch.io;

import com.sunwayworld.baseline.framework.override.LimsExcelHelper;
import com.sunwayworld.basemodule.basedata.batchtype.bean.LimsBatchCategoryBean;
import com.sunwayworld.basemodule.basedata.batchtype.service.LimsBatchCategoryService;
import com.sunwayworld.basemodule.basedata.sampletype.bean.LimsSampleTypeBean;
import com.sunwayworld.basemodule.basedata.sampletype.service.LimsSampleTypeService;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchBean;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleBean;
import com.sunwayworld.basemodule.business.batch.bean.LimsBatchSampleProductBean;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleProductService;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchSampleService;
import com.sunwayworld.basemodule.business.batch.service.LimsBatchService;
import com.sunwayworld.basemodule.coredata.product.bean.LimsProductMainBean;
import com.sunwayworld.basemodule.coredata.product.service.LimsProductMainService;
import com.sunwayworld.basemodule.rm.client.bean.LimsClientBean;
import com.sunwayworld.basemodule.rm.client.service.LimsClientService;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.basemodule.samplemanage.sample.service.LimsSampleService;
import com.sunwayworld.framework.context.ApplicationContextHelper;
import com.sunwayworld.framework.exception.InvalidDataException;
import com.sunwayworld.framework.i18n.I18nHelper;
import com.sunwayworld.framework.io.file.FilePathDTO;
import com.sunwayworld.framework.io.file.FilePathManager;
import com.sunwayworld.framework.mybatis.mapper.MapperParameter;
import com.sunwayworld.framework.mybatis.mapper.MatchPattern;
import com.sunwayworld.framework.mybatis.mapper.SearchFilter;
import com.sunwayworld.framework.spring.annotation.GikamBean;
import com.sunwayworld.framework.utils.BeanUtils;
import com.sunwayworld.framework.utils.StringUtils;
import com.sunwayworld.module.item.file.bean.CoreFileBean;
import com.sunwayworld.module.item.file.bean.CoreFileImportResultDTO;
import com.sunwayworld.module.item.file.function.CoreFileImportFunction;
import com.sunwayworld.module.item.file.utils.CoreFileUtils;
import com.sunwayworld.module.sys.code.bean.CoreCodeBean;
import com.sunwayworld.module.sys.code.service.CoreCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@GikamBean
@Component(value = "LimsBatchImportFileFunction")
public class LimsBatchImportFileFunction implements CoreFileImportFunction {

    @Autowired
    @Lazy
    private CoreCodeService coreCodeService;

    @Autowired
    @Lazy
    LimsSampleTypeService limsSampleTypeService;

    @Autowired
    @Lazy
    LimsClientService limsClientService;

    @Autowired
    @Lazy
    LimsProductMainService limsProductMainService;

    @Autowired
    @Lazy
    LimsBatchService limsBatchService;

    @Autowired
    @Lazy
    LimsBatchSampleService limsBatchSampleService;

    @Autowired
    @Lazy
    LimsSampleService limsSampleService;

    @Autowired
    @Lazy
    LimsBatchCategoryService limsBatchCategoryService;

    @Autowired
    @Lazy
    LimsBatchSampleProductService limsBatchSampleProductService;

    // 标题行所在索引
    private static final int titleRowIndex = 2;

    @Override
    @Transactional
    public CoreFileImportResultDTO apply(CoreFileBean coreFileBean) {
        CoreFileImportResultDTO resultDTO = new CoreFileImportResultDTO();
        List<LimsSampleBean> sampleBeans = LimsExcelHelper.readDataFromExcel(FilePathManager.getLocalPath(CoreFileUtils.toFilePath(coreFileBean)).toString(), titleRowIndex, titleRowIndex + 1, LimsSampleBean.class);
        if (sampleBeans.isEmpty()) {
            throw new InvalidDataException("导入失败！");
        }
        List<String> columns = Arrays.asList("hissampleCode","sampleType", "sampleName", "age", "gender", "productname", "groupId");
        List<String> colNames = Arrays.asList("【分院样本编号】","【样本类型】", "【姓名】", "【年龄】", "【性别】", "【检测项目名称】", "【送检单分组号】");
        // 下拉框
        MapperParameter parameter = new MapperParameter();
        parameter.put("filter_derivativeType", "0");
        List<LimsSampleTypeBean> typeBeans = limsSampleTypeService.selectList(parameter);
        List<CoreCodeBean> genders = coreCodeService.selectListByFilter(SearchFilter.instance().match("codeCategoryId", "gender").filter(MatchPattern.EQ));
        List<CoreCodeBean> ageUnits = coreCodeService.selectListByFilter(SearchFilter.instance().match("codeCategoryId", "ageUnit").filter(MatchPattern.EQ));
        List<LimsClientBean> clientBeans = limsClientService.selectListByFilter(SearchFilter.instance().match("clientStatus", "1").filter(MatchPattern.EQ));
        List<CoreCodeBean> couriers = coreCodeService.selectListByFilter(SearchFilter.instance().match("codeCategoryId", "courier").filter(MatchPattern.EQ));
        List<LimsProductMainBean> productMainBeans = limsProductMainService.selectListByFilter(SearchFilter.instance().match("status", "1").filter(MatchPattern.EQ));
        String batchType = "";
        Optional<LimsSampleBean> os = sampleBeans.stream().filter(s -> s != null && !StringUtils.isBlank(s.getExt$Item("batchType"))).findAny();
        if (os.isPresent()) {
            batchType = os.get().getExt$Item("batchType");
        } else {
            throw new InvalidDataException("文件异常，导入失败！");
        }

        LimsBatchCategoryBean categoryBean = limsBatchCategoryService.selectFirstByFilter(SearchFilter.instance().match("batchTypeCode", batchType).filter(MatchPattern.EQ));
        if (categoryBean == null || categoryBean.getId() == null) {
            throw new InvalidDataException("文件异常，导入失败！");
        }
        // 基因检测送检单样本信息必填项
        if (batchType.equals("B04")) {
            columns = Arrays.asList("groupId", "customerName", "hissampleCode","sampleName",
                "gender", "age", "sampleType", "collectTime", "productname");
            colNames = Arrays.asList("【送检单分组号】", "【送检单位】","【分院样本编号】", "【姓名】",
                "【性别】", "【年龄】", "【样本类型】", "【样本采集时间】", "【检测项目名称】");
        }
        // 联系电话格式校验
        String phonePattern = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}|^(0\\d{2,3})-?(\\d{7,8})$";
        List<String> finalColumns = columns;
        List<String> finalColNames = colNames;
        sampleBeans.stream().filter(Objects::nonNull).forEach(s -> {
            StringBuilder msg = new StringBuilder();
            for (int i = 0; i < finalColumns.size(); i++) {
                Object value = BeanUtils.getPropertyValue(s, finalColumns.get(i));
                if (value == null || (value.getClass().equals(String.class) && value.equals(""))) {
                    msg.append(finalColNames.get(i));
                }
            }
            if (msg.length() > 0) {
                msg.append(" 为必填项；");
            }
            if (msg.length() > 0) {
                if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                    s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat(msg.toString()));
                } else {
                    s.setExt$Item("validateimpmsg", msg.toString());
                }
            }
            if (!StringUtils.isBlank(s.getSampleType())) {
                Optional<LimsSampleTypeBean> optional = typeBeans.stream().filter(t -> t.getSampleTypeName().equals(s.getSampleType())).findAny();
                if (optional.isPresent()) {
                    s.setSampleTypeCode(optional.get().getSampleTypeCode());
                } else {
                    if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                        s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat("【样本类型】无法识别；"));
                    } else {
                        s.setExt$Item("validateimpmsg", "【样本类型】无法识别；");
                    }
                }
            }
            if (!StringUtils.isBlank(s.getGender())) {
                Optional<CoreCodeBean> optional = genders.stream().filter(g -> g.getCodeName().equals(s.getGender())).findAny();
                if (optional.isPresent()) {
                    s.setGender(optional.get().getCode());
                } else {
                    if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                        s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat("【性别】无法识别；"));
                    } else {
                        s.setExt$Item("validateimpmsg", "【性别】无法识别；");
                    }
                }
            }
            if (!StringUtils.isBlank(s.getAgeUnit())) {
                Optional<CoreCodeBean> optional = ageUnits.stream().filter(g -> g.getCodeName().equals(s.getAgeUnit())).findAny();
                if (optional.isPresent()) {
                    s.setGender(optional.get().getCode());
                } else {
                    if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                        s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat("【年龄单位】无法识别；"));
                    } else {
                        s.setExt$Item("validateimpmsg", "【年龄单位】无法识别；");
                    }
                }
            }
            if (!StringUtils.isBlank(s.getCourier())) {
                Optional<CoreCodeBean> optional = couriers.stream().filter(g -> g.getCodeName().equals(s.getCourier())).findAny();
                if (optional.isPresent()) {
                    s.setCourier(optional.get().getCode());
                } else {
                    if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                        s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat("【物流公司】无法识别；"));
                    } else {
                        s.setExt$Item("validateimpmsg", "【物流公司】无法识别；");
                    }
                }
            }
            if (!StringUtils.isBlank(s.getCustomerName())) {
                Optional<LimsClientBean> optional = clientBeans.stream().filter(c -> c.getClientName().equals(s.getCustomerName())).findAny();
                if (optional.isPresent()) {
                    s.setCustomerCode(optional.get().getClientCode());
                    if (StringUtils.isBlank(s.getCustomerName())) {
                        s.setCustomerName(optional.get().getClientName());
                        // 客户单位简
                        s.setCustomerNickName(optional.get().getClientShortName());
                    }
                } else {
                    if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                        s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat("【送检客户】无法识别；"));
                    } else {
                        s.setExt$Item("validateimpmsg", "【送检客户】无法识别；");
                    }
                }
            }
            if (!StringUtils.isBlank(s.getExt$Item("productname"))) {
                String productName = s.getExt$Item("productname");
                if (productMainBeans.stream().noneMatch(p -> p.getProductName().equals(productName))) {
                    if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                        s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat("【" + productName + "】无该检测项目；"));
                    } else {
                        s.setExt$Item("validateimpmsg", "【" + productName + "】无该检测项目；");
                    }
                }
            }
            if (!StringUtils.isBlank(s.getSamplePhone()) && !s.getSamplePhone().matches(phonePattern)) {
                if (!StringUtils.isBlank(s.getExt$Item("validateimpmsg"))) {
                    s.setExt$Item("validateimpmsg", s.getExt$Item("validateimpmsg").concat("【联系电话】格式不正确；"));
                } else {
                    s.setExt$Item("validateimpmsg", "【联系电话】格式不正确；");
                }
            }
            s.setSampleCode(ApplicationContextHelper.getNextSequence("T_LIMS_SAMPLECODE"));
        });
        // 返还校验结果
        if (sampleBeans.stream().anyMatch(i -> !StringUtils.isEmpty(i.getExt$Item("validateimpmsg")))) {
            FilePathDTO fr = CoreFileUtils.toFilePath(coreFileBean);
            FilePathDTO filePathDTO = LimsExcelHelper.writeImportFailureListAsExcel(FilePathManager.getLocalPath(fr).toString(), sampleBeans, titleRowIndex, titleRowIndex + 1, "导入错误信息.xlsx", false);
            resultDTO.setUrl(FilePathManager.getUrl(filePathDTO));
            resultDTO.setMessage("导入失败");
            return resultDTO;
        }

        Map<String, List<LimsSampleBean>> groupByGroupId = sampleBeans.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(s -> s.getExt$Item("groupId")));
        List<LimsBatchBean> insertBatchs = new ArrayList<>();
        List<LimsBatchSampleBean> insertBSs = new ArrayList<>();
        List<LimsBatchSampleProductBean> insertBSPs = new ArrayList<>();

        String finalBatchType = batchType;
        groupByGroupId.forEach((g, temp) -> {
            LimsBatchBean batchBean = new LimsBatchBean();
            insertBatchs.add(batchBean);
            batchBean.setId(ApplicationContextHelper.getNextIdentity());
            batchBean.setBatchCode(ApplicationContextHelper.getNextSequence(limsBatchService.getDao().getTable(), "D"));
            batchBean.setBatchType(finalBatchType);
            batchBean.setBatchCategory(categoryBean.getBatchCategory());

            temp.forEach(s -> {
                s.setId(ApplicationContextHelper.getNextIdentity());
                s.setOriNo(s.getSampleCode());

                LimsBatchSampleBean batchSampleBean = new LimsBatchSampleBean();
                insertBSs.add(batchSampleBean);
                batchSampleBean.setId(ApplicationContextHelper.getNextIdentity());
                batchSampleBean.setBatchId(batchBean.getId());
                batchSampleBean.setBatchCode(batchBean.getBatchCode());
                batchSampleBean.setSampleId(s.getId());
                batchSampleBean.setSampleCode(s.getSampleCode());
                // 将送检客户信息同步到订单表，理论同一分组下，送检单位必须相同
                batchBean.setCustomerCode(s.getCustomerCode());
                batchBean.setCustomerName(s.getCustomerName());
                batchBean.setCustomerNickName(s.getCustomerNickName());
                List<String> productname = Arrays.asList(s.getExt$Item("productname").split(","));
                productname.forEach(pn -> {
                    productMainBeans.stream().filter(pm -> pm.getProductName().equals(pn)).findAny().ifPresent(pm -> {
                        LimsBatchSampleProductBean productBean = new LimsBatchSampleProductBean();
                        productBean.setId(ApplicationContextHelper.getNextIdentity());
                        productBean.setBatchId(batchSampleBean.getBatchId());
                        productBean.setBatchCode(batchSampleBean.getBatchCode());
                        productBean.setBatchSampleId(batchSampleBean.getId());
                        productBean.setSampleId(s.getId());
                        productBean.setSampleCode(s.getSampleCode());
                        productBean.setProductId(pm.getId());
                        productBean.setProductCode(pm.getProductCode());
                        productBean.setProductName(pm.getProductName());
                        insertBSPs.add(productBean);
                    });
                });
            });

        });
        limsSampleService.getDao().insert(sampleBeans);
        limsBatchService.getDao().insert(insertBatchs);
        limsBatchSampleService.getDao().insert(insertBSs);
        limsBatchSampleProductService.getDao().insert(insertBSPs);

        resultDTO.setMessage(I18nHelper.getMessage("CORE.MODULE.SYS.DPCONFIGS.TIP.IMPORT_SUCCESS"));
        return resultDTO;
    }

    @Override
    public boolean test(CoreFileBean coreFile, String service) {
        return true;
    }
}
